package modbus_master_connector

import (
	"go-iot-gateway/internal/apk/maths"
	conf_table_define "go-iot-gateway/internal/conf_table/define"
	"strconv"
)

// tcp协议说明
type TCPProtocolInfo struct {
	MessageSequenceEnable                     bool   //0		启用报文序列号	十进制	启用
	FixedLocalPort                            uint16 //1		固定本地端口(0随机)	十进制	0
	ClearDataOnCommunicationInterruption      bool   //2		通讯中断数据(不含开关量)清零	十进制	不清零
	ClearSwitchingOnCommunicationInterruption bool   //3		通讯中断开关量清零	十进制	不清零
	FailTimeOfCommunicationInterruption       uint16 //4		触发通讯中断的连续失败次数	十进制	3
	NumOfRegisterPerFrame                     uint16 //5		单帧寄存器最大个数(0手动分组,最大120)	十进制	120
	ResponseBytesLen                          uint8  //6		响应报文字节数长度(单位i字节，默认1字节)	十进制	0
	NumOfRegisterFun04                        uint8  //7		04功能码寄存器字节数(默认2个)	十进制	0
}

func NewTCPProtocolInfo(protocolConfInfos []*conf_table_define.ProtocolInfo) *TCPProtocolInfo {
	protocolInfo := &TCPProtocolInfo{
		MessageSequenceEnable:                     true,
		FixedLocalPort:                            0,
		ClearDataOnCommunicationInterruption:      false,
		ClearSwitchingOnCommunicationInterruption: false,
		FailTimeOfCommunicationInterruption:       3,
		NumOfRegisterPerFrame:                     120,
		ResponseBytesLen:                          1,
		NumOfRegisterFun04:                        2,
	}

	if protocolConfInfos == nil || len(protocolConfInfos) <= 0 {
		return protocolInfo
	}
	for _, info := range protocolConfInfos {
		//if channel_define.MODBUS_TCP_MASTER != info.F_pno {
		//	logger.Connector().Error("协议创建异常,类型不匹配")
		//	continue
		//}
		switch info.F_no {
		case 0:
			protocolInfo.MessageSequenceEnable = info.F_value == "1"
		case 1:
			parseUint, err := strconv.ParseUint(info.F_value, 10, 16)
			if err != nil {
				return nil
			}
			protocolInfo.FixedLocalPort = uint16(parseUint)
		case 2:
			protocolInfo.ClearDataOnCommunicationInterruption = info.F_value == "1"
		case 3:
			protocolInfo.ClearSwitchingOnCommunicationInterruption = info.F_value == "1"
		case 4:
			parseUint, err := strconv.ParseUint(info.F_value, 10, 16)
			if err != nil {
				return nil
			}
			protocolInfo.FailTimeOfCommunicationInterruption = uint16(parseUint)
		case 5:
			parseUint, err := strconv.ParseUint(info.F_value, 10, 16)
			if err != nil {
				return nil
			}
			protocolInfo.NumOfRegisterPerFrame = maths.MinUint16(uint16(parseUint), 120)
		case 6:
			parseUint, err := strconv.ParseUint(info.F_value, 10, 8)
			if err != nil {
				return nil
			}
			protocolInfo.ResponseBytesLen = uint8(parseUint)
		case 7:
			parseUint, err := strconv.ParseUint(info.F_value, 10, 8)
			if err != nil {
				return nil
			}
			protocolInfo.NumOfRegisterFun04 = uint8(parseUint)
		}
	}

	return protocolInfo
}

// rtu
// 0		MODBUS-RTU	CRC校验高低位相反	十进制	不相反
// 3		MODBUS-RTU	触发通讯中断的连续失败次数	十进制	3
// 5		MODBUS-RTU	不校验CRC码	十进制	校验
// 8		MODBUS-RTU	02寄存器字节数(0则按标准处理)	十进制	0
// 9		MODBUS-RTU	05命令写值的字节数(0则按标准处理)	十进制	0
// 10		MODBUS-RTU	05命令合的值(0则按标准处理)	十六进制	0
// 11		MODBUS-RTU	05命令分的值(0则按标准处理)	十六进制	0
// 12		MODBUS-RTU	模拟量寄存器字节数	十进制	2
// 13		MODBUS-RTU	按字节计算02请求长度	十进制	0
// 14		MODBUS-RTU	整点对时,0~23(大于23不执行)	十进制	24
// 15		MODBUS-RTU	对时周期:分钟(0不对时)	十进制	0
// 16		MODBUS-RTU	对时报文	字符串	001004BA00060CNNNNYYYYRRRRSSSSFFFFMMMM
// 18		MODBUS-RTU	读失败后，跳过设备	十进制	0
// 19		MODBUS-RTU	 不相等才写(YK除外)	十进制	0
// 20		MODBUS-RTU	 YC变化限制触发次数（0不限制）	十进制	0
// 22		MODBUS-RTU	写成功后不回读设备	十进制	0
// 23		MODBUS-RTU	群控群调广播地址	十六进制	-1
// 24		MODBUS-RTU	快速扫描测点(物模型，写值后触发)	字符串
// 25		MODBUS-RTU	快速扫描次数	十进制	5
// 26		MODBUS-RTU	广播写次数(最大10次)	十进制	3
// 27		MODBUS-RTU	广播间隔(ms)	十进制	500
type RTUProtocolInfo struct {
	ClearDataOnCommunicationInterruption      bool   // 1		MODBUS-RTU	通讯中断数据(不含开关量)清零	十进制	不清零
	ClearSwitchingOnCommunicationInterruption bool   // 2		MODBUS-RTU	通讯中断开关量清零	十进制	不清零
	RepeatWriting                             bool   // 4		MODBUS-RTU	写值时重复写入1次	十进制	否
	NumOfRegisterPerFrame                     uint16 // 6		MODBUS-RTU	单帧寄存器最大个数(0手动分组,最大125)	十进制	125
	WriteRetryOnFail                          uint8  // 7		MODBUS-RTU	写值失败后，重写次数(最多10次)	十进制	0
	ReadRetryOnFail                           uint8  // 17		MODBUS-RTU	读失败后，重读次数(最多10次)	十进制	0
	RepeatRead                                uint8  // 21		MODBUS-RTU	重复读取次数	十进制	0
}

func NewRTUProtocolInfo(protocolConfInfos []*conf_table_define.ProtocolInfo) *RTUProtocolInfo {
	protocolInfo := &RTUProtocolInfo{
		ClearDataOnCommunicationInterruption:      false,
		ClearSwitchingOnCommunicationInterruption: false,
		RepeatWriting:         false,
		NumOfRegisterPerFrame: 120,
		WriteRetryOnFail:      0,
		ReadRetryOnFail:       1,
		RepeatRead:            0,
	}

	if protocolConfInfos == nil || len(protocolConfInfos) <= 0 {
		return protocolInfo
	}

	for _, info := range protocolConfInfos {
		switch info.F_no {
		case 1:
			protocolInfo.ClearDataOnCommunicationInterruption = info.F_value == "1"
		case 2:
			protocolInfo.ClearSwitchingOnCommunicationInterruption = info.F_value == "1"
		case 4:
			protocolInfo.RepeatWriting = info.F_value == "1"
		case 6:
			parseUint, err := strconv.ParseUint(info.F_value, 10, 16)
			if err != nil {
				return nil
			}
			protocolInfo.NumOfRegisterPerFrame = maths.MinUint16(uint16(parseUint), 120)
		case 7:
			parseUint, err := strconv.ParseUint(info.F_value, 10, 8)
			if err != nil {
				return nil
			}
			protocolInfo.WriteRetryOnFail = maths.MinUint8(uint8(parseUint), 30)
		case 17:
			parseUint, err := strconv.ParseUint(info.F_value, 10, 8)
			if err != nil {
				return nil
			}
			protocolInfo.ReadRetryOnFail = maths.MinUint8(uint8(parseUint), 10)
		case 21:
			parseUint, err := strconv.ParseUint(info.F_value, 10, 8)
			if err != nil {
				return nil
			}
			protocolInfo.RepeatRead = maths.MinUint8(uint8(parseUint), 10)
		}

	}

	return protocolInfo
}
